import { messages } from "share/common";
import React, { PropTypes, Component } from 'react';
import { Select, Spin } from 'antd'
const Option = Select.Option;
import selectorData from 'share/selectorData'
import httpFetch from 'share/httpFetch'
import debounce from 'lodash.debounce';

/**
 * 多选selector，使用的还是selectorData
 * 这个组件保持了进出数据结构一致，不再会搞什么onlyNeed之类的东西
 * 不用维护值类型和selectorItem后跟selector比清爽了好多，舒服
 */
class MultiSelector extends Component {

  constructor(props) {
    super(props);
    this.state = {
      value: [],
      options: [],
      loading: false
    };
    this.fetched = false;
    this.onSearch = debounce(this.onSearch, 250);
  }

  componentDidMount() {
    if('value' in this.props)
      this.setValue(this.props.value);
  }

  componentWillReceiveProps(nextProps) {
    if('value' in nextProps)
      this.setValue(nextProps.value);
  }

  dispatchOnchange() {
    const { value } = this.state;
    const { onChange } = this.props;
    onChange && onChange(value.map(v => v.data));
  }

  setValue = value => {
    let selectorItem = this.getSelectorItem();
    const { key, label } = selectorItem;
    let { options } = this.state;
    const { itemMap } = this.props;
    if(value && Array.isArray(value)) {
      let valueOptions = value.map(option => ({
        key: typeof key === 'string' ? option[key] : key(option),
        label: typeof label === 'string' ? option[label] : label(option),
        data: option
      }));
      let extraOptions = [];
      valueOptions.map(option => {
        if(!options.find(o => o.key === option.key))
          extraOptions.push(option);
      });
      options = extraOptions.concat(options);
      this.setState({ value: valueOptions, options }, () => {
        //其实进出都一致的话itemMap这种参数应该不再需要了，除非是你想把初始undefined转成[]
        itemMap && this.dispatchOnchange();
      });
    } else {
      this.setState({ value: [] })
    }
  };

  getSelectorItem = () => {
    //直接把这个东西放在外部，内部不再维护
    const { selectorItem, type } = this.props;
    return selectorItem || selectorData[type];
  };

  getOptions = keywords => {
    const { params, filter } = this.props;
    let selectorItem = this.getSelectorItem();
    const { service, url, searchKey, map, listKey, key, label } = selectorItem;
    this.setState({ loading: true });
    let extraParams = (searchKey && keywords) ? { [searchKey]: keywords } : {};
    let fetch = service ? service(keywords) : httpFetch.get(url, { ...params, ...extraParams });
    fetch.then(res => {
      let options = [];
      if(map)
        options = map(res.data);
      else {
        if(listKey) {
          let keys = selectorItem.listKey.split('.');
          options = res.data;
          keys.map(key => {
            options = options[key];
          })
        } else {
          options = res.data;
        }
      }
      this.setState({
        loading: false,
        options: options.filter(filter).map(option => ({
          key: typeof key === 'string' ? option[key] : key(option),
          label: typeof label === 'string' ? option[label] : label(option),
          data: option
        }))
      })
    }).catch(e => {
      this.setState({ loading: false });
    })
  };

  onFocus = () => {
    let selectorItem = this.getSelectorItem();
    const { searchKey, dynamicUrl } = selectorItem;
    if(searchKey) {
      this.getOption();
    } else {
      if(!this.fetched || dynamicUrl) {
        this.getOptions();
      }
    }
  };

  onSearch = key => {
    let selectorItem = this.getSelectorItem();
    const { searchKey } = selectorItem;
    if(searchKey) {
      this.getOptions(key);
    }
  };

  onChange = nextValue => {
    const { value, options } = this.state;
    if(nextValue.length > value.length) {
      value.push(options.find(option => option.key === nextValue[nextValue.length - 1]));
      this.setState({ value }, this.dispatchOnchange);
    } else if(nextValue.length === 0) {
      this.setState({ value: [] }, this.dispatchOnchange);
    } else {
      this.setState({ value: value.filter(option => nextValue.indexOf(option.key) > -1) }, this.dispatchOnchange);
    }
  };

  render() {
    const { value, options, loading } = this.state;
    const { disabled, placeholder, allowClear, getPopupContainer, size } = this.props;
    return (
      <Select
        allowClear={allowClear}
        onChange={this.onChange}
        style={{ width: '100%' }}
        mode='multiple'
        placeholder={placeholder}
        onFocus={this.onFocus}
        size={size}
        value={value.map(v => v.key)}
        onSearch={this.onSearch}
        disabled={disabled}
        getPopupContainer={getPopupContainer}
        notFoundContent={loading ? <Spin size="small"/> : messages('common.unmatched')/*无匹配结果*/}
        optionFilterProp='children'
      >
        {options.map(option => (
          <Option
            key={option.key}
            value={option.key}
            style={{ whiteSpace: 'pre-wrap', wordWrap: ' break-word' }}
            title={option.label}
          >
            {option.label}
          </Option>
        ))}
      </Select>
    );
  }

  static propTypes = {
    type: PropTypes.string,
    selectorItem: PropTypes.object,
    params: PropTypes.object,
    disabled: PropTypes.bool,
    allowClear: PropTypes.bool,
    value: PropTypes.array,
    placeholder: PropTypes.string,
    onChange: PropTypes.func,
    filter: PropTypes.func,
    size: PropTypes.string,
    itemMap: PropTypes.bool
  };

  static defaultProps = {
    disabled: false,
    allowClear: true,
    placeholder: messages('common-1.key52')/*请选择temp*/,
    params: {},
    getPopupContainer: triggerNode => triggerNode.parentNode,
    filter: option => true,
    size: 'default',
    itemMap: false
  };
}

MultiSelector.getSelectorData = type => selectorData[type];

export default MultiSelector;
